home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 418_04 / abstree.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-02  |  23.4 KB  |  793 lines

  1. /* abstree.c
  2.  * RasMol2 Molecular Graphics
  3.  * Roger Sayle, February 1994
  4.  * Version 2.3
  5.  */
  6. #include "rasmol.h"
  7.  
  8. #ifdef IBMPC
  9. #include <malloc.h>
  10. #endif
  11. #ifndef sun386
  12. #include <stdlib.h>
  13. #endif
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. #include <math.h>
  18.  
  19. #define ABSTREE
  20. #include "molecule.h"
  21. #include "abstree.h"
  22.  
  23.  
  24. #define ExprPool    16
  25. #define SetPool     4
  26.  
  27. typedef struct _SymEntry {
  28.                 struct _SymEntry __far *lft;
  29.                 struct _SymEntry __far *rgt;
  30.                 AtomSet __far *defn;
  31.                 char *ident;
  32.                 } SymEntry;
  33.  
  34. static SymEntry __far *SymbolTable;
  35. static SymEntry __far *FreeEntry;
  36. static AtomSet __far *FreeSet;
  37. static Expr *FreeExpr;
  38. static Expr FalseExpr;
  39. static Expr TrueExpr;
  40.  
  41. /* Macros for commonly used loops */
  42. #define ForEachAtom  for(chain=Database->clist;chain;chain=chain->cnext) \
  43.                      for(group=chain->glist;group;group=group->gnext)    \
  44.                      for(aptr=group->alist;aptr;aptr=aptr->anext)
  45.  
  46.  
  47. #define BitAcidic       0x001
  48. #define BitAliphatic    0x002
  49. #define BitAromatic     0x004
  50. #define BitBasic        0x008
  51. #define BitBuried       0x010
  52. #define BitCyclic       0x020
  53. #define BitHydrophobic  0x040
  54. #define BitMedium       0x080
  55. #define BitNeutral      0x100
  56. #define BitSmall        0x200
  57.  
  58. #define BitCharged      0x009
  59. #define BitNotLarge     0x280
  60.  
  61. /* Acyclic = !Cyclic         */
  62. /* Large = !Medium && !Small */
  63. /* Polar = !Hydrophobic      */
  64. /* Surface = !Buried         */
  65.  
  66.  
  67. static int AminoProp[] = {
  68.         /*ALA*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral |
  69.                  BitSmall,
  70.         /*GLY*/  BitAliphatic | BitHydrophobic | BitNeutral | BitSmall,
  71.         /*LEU*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral,
  72.         /*SER*/  BitNeutral | BitSmall,
  73.         /*VAL*/  BitAliphatic | BitBuried | BitHydrophobic | BitMedium |
  74.                  BitNeutral,
  75.         /*THR*/  BitMedium | BitNeutral,
  76.         /*LYS*/  BitBasic,
  77.         /*ASP*/  BitAcidic | BitMedium,
  78.         /*ILE*/  BitAliphatic | BitBuried | BitHydrophobic | BitNeutral,
  79.         /*ASN*/  BitMedium | BitNeutral,
  80.         /*GLU*/  BitAcidic,
  81.         /*PRO*/  BitCyclic | BitHydrophobic | BitMedium | BitNeutral,
  82.         /*ARG*/  BitBasic,
  83.         /*PHE*/  BitAromatic | BitBuried | BitCyclic | BitHydrophobic |
  84.                  BitNeutral,
  85.         /*GLN*/  BitNeutral,
  86.         /*TYR*/  BitAromatic | BitCyclic | BitNeutral,
  87.         /*HIS*/  BitAromatic | BitBasic | BitCyclic | BitNeutral,
  88.         /*CYS*/  BitBuried | BitMedium | BitNeutral,
  89.         /*MET*/  BitBuried | BitHydrophobic | BitNeutral,
  90.         /*TRP*/  BitAromatic | BitBuried | BitCyclic | BitHydrophobic |
  91.                  BitNeutral,
  92.  
  93.         /*ASX*/  BitMedium | BitNeutral,
  94.         /*GLX*/  BitNeutral,
  95.         /*PCA*/  BitCyclic | BitHydrophobic | BitMedium | BitNeutral,
  96.         /*HYP*/  BitCyclic | BitMedium | BitNeutral
  97.         };
  98.  
  99.  
  100. static void FatalExprError(ptr)
  101.     char *ptr;
  102. {
  103.     char buffer[80];
  104.  
  105.     sprintf(buffer,"Expression Error: %s!",ptr);
  106.     RasMolFatalExit(buffer);
  107. }
  108.  
  109.  
  110. #if defined(__STDC__) || defined(IBMPC)
  111. /* Function Prototypes */
  112. static AtomSet __far *SetInsert( AtomSet __far*, Atom __far* );
  113. static int IsWithinRadius( AtomSet __far*, Long );
  114. static int IsSetMember( AtomSet __far* );
  115. #endif
  116.  
  117.  
  118. static AtomSet __far *SetInsert( ptr, item )
  119.     AtomSet __far *ptr;  Atom __far *item;
  120. {
  121.     register AtomSet __far *temp;
  122.     register int i;
  123.  
  124.     if( ptr && (ptr->count<SetSize) )
  125.     {   ptr->data[ptr->count] = item;
  126.         ptr->count++;
  127.         return( ptr );
  128.     }
  129.  
  130.     if( !FreeSet )
  131.     {   temp = (AtomSet __far*)_fmalloc( SetPool*sizeof(AtomSet) );
  132.         if( !temp ) FatalExprError("Memory allocation failed");
  133.         for( i=1; i<SetPool; i++ )
  134.         {    temp->next = FreeSet;
  135.              FreeSet = temp++;
  136.         }
  137.     } else
  138.     {   temp = FreeSet;
  139.         FreeSet = temp->next;
  140.     }
  141.  
  142.     temp->data[0] = item;
  143.     temp->next = ptr;
  144.     temp->count = 1;
  145.     return( temp );
  146. }
  147.  
  148.  
  149. static int IsWithinRadius( ptr, limit )
  150.     AtomSet __far *ptr;
  151.     Long limit;
  152. {
  153.     register Atom __far *aptr;
  154.     register Long dx,dy,dz;
  155.     register Long dist;
  156.     register int i;
  157.  
  158.     while( ptr )
  159.     {   for( i=0; i<ptr->count; i++ )
  160.         {    aptr = ptr->data[i];
  161.              dx = QAtom->xorg-aptr->xorg; if( (dist=dx*dx)>limit ) continue;
  162.              dy = QAtom->yorg-aptr->yorg; if( (dist+=dy*dy)>limit ) continue;
  163.              dz = QAtom->zorg-aptr->zorg; if( (dist+=dz*dz)>limit ) continue;
  164.              return( True );
  165.         }
  166.         ptr = ptr->next;
  167.     }
  168.     return( False );
  169. }
  170.  
  171.  
  172. static int IsSetMember( ptr )
  173.     AtomSet __far *ptr;
  174. {
  175.     register int i;
  176.  
  177.     while( ptr )
  178.     {   for( i=0; i<ptr->count; i++ )
  179.             if( ptr->data[i] == QAtom )
  180.                 return( True );
  181.         ptr = ptr->next;
  182.     }
  183.     return( False );
  184. }
  185.  
  186.  
  187. void DeleteAtomSet( ptr )
  188.     AtomSet __far *ptr;
  189. {
  190.     register AtomSet __far *temp;
  191.  
  192.     if( (temp = ptr) )
  193.     {   while( temp->next )
  194.             temp = temp->next;
  195.         temp->next = FreeSet;
  196.         FreeSet = ptr;
  197.     }
  198. }
  199.  
  200.  
  201. Expr *AllocateNode()
  202. {
  203.     register Expr *ptr;
  204.     register int i;
  205.  
  206.     if( !FreeExpr )
  207.     {   ptr = (Expr*)malloc( ExprPool*sizeof(Expr) );
  208.         if( !ptr ) FatalExprError("Memory allocation failed");
  209.         for( i=1; i<ExprPool; i++ )
  210.         {   ptr->rgt.ptr = FreeExpr;
  211.             FreeExpr = ptr++;
  212.         }
  213.     } else
  214.     {   ptr = FreeExpr;
  215.         FreeExpr = ptr->rgt.ptr;
  216.     }
  217.     ptr->rgt.ptr = NULL;
  218.     ptr->lft.ptr = NULL;
  219.     return( ptr );
  220. }
  221.  
  222.  
  223. void DeAllocateExpr( expr )
  224.     Expr *expr;
  225. {
  226.     if( !expr ) return;
  227.     if( (expr == &FalseExpr) ||
  228.         (expr == &TrueExpr) ) 
  229.         return;
  230.  
  231.     if( expr->type!=OpWithin )
  232.     {   if( !(expr->type&(OpLftProp|OpLftVal)) )
  233.             DeAllocateExpr( expr->lft.ptr );
  234.         if( !(expr->type&(OpRgtProp|OpRgtVal)) )
  235.             DeAllocateExpr( expr->rgt.ptr );
  236.     } else DeleteAtomSet( expr->rgt.set );
  237.         
  238.     expr->rgt.ptr = FreeExpr;
  239.     FreeExpr = expr;
  240. }
  241.  
  242.  
  243. int GetElemIdent( aptr )
  244.     Atom __far *aptr;
  245. {
  246.     register char *ptr;
  247.  
  248.     ptr = ElemDesc[aptr->refno];
  249.     switch( *ptr )
  250.     {   case(' '):  switch( ptr[1] )
  251.                     {   case('B'): return( HandB );
  252.                         case('C'): return( HandC );
  253.                         case('D'): return( HandH );
  254.                         case('F'): return( HandF );
  255.                         case('H'): return( HandH );
  256.                         case('I'): return( HandI );
  257.                         case('K'): return( HandK );
  258.                         case('N'): return( HandN );
  259.                         case('O'): return( HandO );
  260.                         case('P'): return( HandP );
  261.                         case('S'): return( HandS );
  262.                     }
  263.                     break;
  264.  
  265.         case('A'):  if( ptr[1]=='G' )
  266.                     {   return( HandAg );
  267.                     } else if( ptr[1]=='L' )
  268.                     {   return( HandAl );
  269.                     } else if( ptr[2]=='U' )
  270.                         return( HandAu );
  271.                     break;
  272.  
  273.         case('B'):  if( ptr[1]=='R' )
  274.                         return( HandBr );
  275.                     break;
  276.  
  277.         case('C'):  switch( ptr[1] )
  278.                     {   case('A'): return( HandCa );
  279.                         case('L'): return( HandCl );
  280.                         case('R'): return( HandCr );
  281.                         case('U'): return( HandCu );
  282.                     }
  283.                     break;
  284.  
  285.         case('F'):  if( ptr[1]=='E' )
  286.                         return( HandFe );
  287.                     break;
  288.  
  289.         case('H'):  if( ptr[1]=='E' )
  290.                         return( HandHe );
  291.                     break;
  292.  
  293.         case('L'):  if( ptr[1]=='I' )
  294.                         return( HandLi );
  295.                     break;
  296.  
  297.         case('M'):  if( ptr[1]=='G' )
  298.                     {   return( HandMg );
  299.                     } else if( ptr[1]=='N' )
  300.                         return( HandMn );
  301.                     break;
  302.  
  303.         case('N'):  if( ptr[1]=='A' )
  304.                     {   return( HandNa );
  305.                     } else if( ptr[1]=='I' )
  306.                         return( HandNi );
  307.                     break;
  308.  
  309.         case('S'):  if( ptr[1]=='I' )
  310.                         return( HandSi );
  311.                     break;
  312.  
  313.         case('Z'):  if( ptr[1]=='N' )
  314.                         return( HandZn );
  315.                     break;
  316.     }
  317.  
  318.     if( (*ptr>='0') && (*ptr<='9') )
  319.         if( (ptr[1]=='H') || (ptr[1]=='D') )
  320.             return( HandH );
  321.  
  322.     return( 0 );
  323. }
  324.  
  325.  
  326. static int EvaluateProperty( prop )
  327.     int prop;
  328. {
  329.     switch( prop )
  330.     {   case( PropIdent ):    return( QAtom->serno );
  331.         case( PropXCord ):    return( (int)QAtom->xorg );
  332.         case( PropYCord ):    return( (int)QAtom->yorg );
  333.         case( PropZCord ):    return( (int)QAtom->zorg );
  334.         case( PropTemp ):     return( QAtom->temp );
  335.         case( PropName ):     return( QAtom->refno );
  336.         case( PropResId ):    return( QGroup->serno );
  337.         case( PropResName ):  return( QGroup->refno );
  338.         case( PropChain ):    return( QChain->ident );
  339.         case( PropSelect ):   return( QAtom->flag&SelectFlag );
  340.         case( PropRad ):      if( QAtom->flag&SphereFlag )
  341.                               {   return( QAtom->radius );
  342.                               } else return( 0 );
  343.  
  344.         
  345.         /* Predicates stored in flags */
  346.         case( PredBonded ):       return( !(QAtom->flag&NonBondFlag) );
  347.         case( PredHydrogen ):     return( QAtom->flag&HydrogenFlag );
  348.         case( PredHetero ):       return( QAtom->flag&HeteroFlag );
  349.         case( PredCystine ):      return( QGroup->flag&CystineFlag );
  350.         case( PredHelix ):        return( QGroup->flag&HelixFlag );
  351.         case( PredSheet ):        return( QGroup->flag&SheetFlag );
  352.         case( PredTurn ):         return( QGroup->flag&TurnFlag );
  353.  
  354.         /* Residue type predicates */
  355.         case( PredDNA ):
  356.         case( PredRNA ):
  357.         case( PredNucleic ):      return( IsNucleo(QGroup->refno) );
  358.         case( PredProtein ):      return( IsProtein(QGroup->refno) );
  359.         case( PredAmino ):        return( IsAmino(QGroup->refno) );
  360.         case( PredWater ):        return( IsWater(QGroup->refno) );
  361.         case( PredSolvent ):      return( IsSolvent(QGroup->refno) );
  362.         case( PredIon ):          return( IsIon(QGroup->refno) );
  363.  
  364.         /* General Predicates */
  365.         case( PredAlpha ):        return( IsAmino(QGroup->refno) &&
  366.                                           IsAlphaCarbon(QAtom->refno) );
  367.         case( PredBackbone ):     return( (IsAmino(QGroup->refno) && 
  368.                                            IsAminoBackbone(QAtom->refno)) ||
  369.                                           (IsNucleo(QGroup->refno) &&
  370.                                            IsNucleicBackbone(QAtom->refno)) );
  371.         case( PredLigand ):       return( (QAtom->flag&HeteroFlag) &&
  372.                                           !IsSolvent(QGroup->refno) );
  373.         case( PredSidechain ):    return( IsAmino(QGroup->refno) &&
  374.                                           !IsAminoBackbone(QAtom->refno) );
  375.  
  376.         /* Nucleic Acid Classifications */
  377.         case( PredAT ):           return( IsAdenine(QGroup->refno) ||
  378.                                           IsThymine(QGroup->refno) );
  379.         case( PredCG ):           return( IsCytosine(QGroup->refno) ||
  380.                                           IsGuanine(QGroup->refno) );
  381.         case( PredPyrimidine ):   return( IsPyrimidine(QGroup->refno) );
  382.         case( PredPurine ):       return( IsPurine(QGroup->refno) );
  383.  
  384.  
  385.         /* Amino Acid Classifications */
  386.         case( PredAcidic ):       return( IsAmino(QGroup->refno) &&
  387.                                   AminoProp[QGroup->refno]&BitAcidic );
  388.  
  389.         case( PredAcyclic ):      return( IsAmino(QGroup->refno) &&
  390.                                   !(AminoProp[QGroup->refno]&BitCyclic) );
  391.  
  392.         case( PredAliphatic ):    return( IsAmino(QGroup->refno) &&
  393.                                   AminoProp[QGroup->refno]&BitAliphatic );
  394.  
  395.         case( PredAromatic ):     return( IsAmino(QGroup->refno) &&
  396.                                   AminoProp[QGroup->refno]&BitAromatic );
  397.  
  398.         case( PredBasic ):        return( IsAmino(QGroup->refno) &&
  399.                                   AminoProp[QGroup->refno]&BitBasic );
  400.  
  401.         case( PredBuried ):       return( IsAmino(QGroup->refno) &&
  402.                                   AminoProp[QGroup->refno]&BitBuried );
  403.  
  404.         case( PredCharged ):      return( IsAmino(QGroup->refno) &&
  405.                                   AminoProp[QGroup->refno]&BitCharged );
  406.  
  407.         case( PredCyclic ):       return( IsAmino(QGroup->refno) &&
  408.                                   AminoProp[QGroup->refno]&BitCyclic );
  409.  
  410.         case( PredHydrophobic ):  return( IsAmino(QGroup->refno) &&
  411.                                   AminoProp[QGroup->refno]&BitHydrophobic );
  412.                  
  413.         case( PredLarge ):        return( IsAmino(QGroup->refno) &&
  414.                                   !(AminoProp[QGroup->refno]&BitNotLarge) );
  415.  
  416.         case( PredMedium ):       return( IsAmino(QGroup->refno) &&
  417.                                   AminoProp[QGroup->refno]&BitMedium );
  418.  
  419.         case( PredNeutral ):      return( IsAmino(QGroup->refno) &&
  420.                                   AminoProp[QGroup->refno]&BitNeutral );
  421.  
  422.         case( PredPolar ):        return( IsAmino(QGroup->refno) &&
  423.                                   !(AminoProp[QGroup->refno]&BitHydrophobic) );
  424.  
  425.         case( PredSmall ):        return( IsAmino(QGroup->refno) &&
  426.                                   AminoProp[QGroup->refno]&BitSmall );
  427.  
  428.         case( PredSurface ):      return( IsAmino(QGroup->refno) &&
  429.                                   !(AminoProp[QGroup->refno]&BitBuried) );
  430.  
  431.     }
  432.     return( True );
  433. }
  434.  
  435.  
  436. int EvaluateExpr( expr )
  437.     Expr *expr;
  438. {
  439.     register int lft, rgt;
  440.  
  441.     if( !expr )
  442.         return( True );
  443.  
  444.     if( expr->type==OpWithin )
  445.     {   if( expr->lft.limit )
  446.         {   return( IsWithinRadius(expr->rgt.set,expr->lft.limit) );
  447.         } else return( IsSetMember(expr->rgt.set) );
  448.     } else if( expr->type==OpMember )
  449.         return( IsSetMember(expr->rgt.set) );
  450.  
  451.     if( expr->type & OpLftVal )
  452.     {   lft = expr->lft.val;
  453.     } else if( expr->type & OpLftProp )
  454.     {   lft = EvaluateProperty( expr->lft.val );
  455.     } else lft = EvaluateExpr( expr->lft.ptr );
  456.  
  457.     if( OpCode(expr)==OpConst ) return( lft );
  458.     if( (OpCode(expr)==OpAnd) && !lft ) return( False );
  459.     if( (OpCode(expr)==OpOr) && lft ) return( True );
  460.     if( OpCode(expr)==OpNot ) return( !lft );
  461.  
  462.     if( expr->type & OpRgtVal )
  463.     {   rgt = expr->rgt.val;
  464.     } else if( expr->type & OpRgtProp )
  465.     {   rgt = EvaluateProperty( expr->rgt.val );
  466.     } else rgt = EvaluateExpr( expr->rgt.ptr );
  467.  
  468.     switch( OpCode(expr) )
  469.     {   case(OpOr):
  470.         case(OpAnd):     return( rgt );
  471.         case(OpLess):    return( lft<rgt );
  472.         case(OpMore):    return( lft>rgt );
  473.         case(OpEqual):   return( lft==rgt );
  474.         case(OpNotEq):   return( lft!=rgt );
  475.         case(OpLessEq):  return( lft<=rgt );
  476.         case(OpMoreEq):  return( lft>=rgt );
  477.     }
  478.     return( True );
  479. }
  480.  
  481.  
  482. AtomSet __far *BuildAtomSet( expr )
  483.     Expr *expr;
  484. {
  485.     register AtomSet __far *ptr;
  486.  
  487.     ptr = (AtomSet __far*)0;
  488.  
  489.     if( Database )
  490.         for( QChain=Database->clist; QChain; QChain=QChain->cnext )
  491.             for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext )
  492.                 for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext )
  493.                     if( EvaluateExpr(expr) )
  494.                         ptr = SetInsert( ptr, QAtom );
  495.  
  496.     return( ptr );
  497. }
  498.  
  499.  
  500.  
  501. int DefineSetExpr( ident, expr )
  502.     char *ident;  Expr *expr;
  503. {
  504.     register SymEntry __far * __far *prev;
  505.     register SymEntry __far *ptr;
  506.     register AtomSet __far *set;
  507.     register int result;
  508.  
  509.     result = True;
  510.     prev = &SymbolTable;
  511.     while( (ptr = *prev) )
  512.     {   result = strcmp(ident,ptr->ident);
  513.         if( !result ) break;  /* Entry Exists! */
  514.         prev = (result<0)? &(ptr->lft) : &(ptr->rgt);
  515.     }
  516.  
  517.     if( result )
  518.     {   if( FreeEntry )
  519.         {   ptr = FreeEntry;
  520.             FreeEntry = ptr->rgt;
  521.         } else /* Allocate SymEntry! */
  522.             if( !(ptr = (SymEntry __far*)_fmalloc(sizeof(SymEntry))) )
  523.                 return( False );
  524.  
  525.         *prev = ptr;
  526.         ptr->ident = ident;
  527.         ptr->defn = (void __far*)0;
  528.         ptr->lft = (void __far*)0;
  529.         ptr->rgt = (void __far*)0;
  530.     } else free(ident);
  531.  
  532.     if( expr )
  533.     {   set = BuildAtomSet(expr);
  534.         if( ptr->defn )
  535.             DeleteAtomSet(ptr->defn);
  536.         DeAllocateExpr(expr);
  537.         ptr->defn = set;
  538.     } else ptr->defn = (void __far*)0;
  539.     return( True );
  540. }
  541.  
  542.  
  543. Expr *LookUpSetExpr( ident )
  544.     char *ident;
  545. {
  546.     register SymEntry __far *ptr;
  547.     register Expr *expr;
  548.     register int result;
  549.  
  550.     result = True;
  551.     ptr = SymbolTable;
  552.     while( ptr )
  553.     {   result = strcmp(ident,ptr->ident);
  554.         if( !result ) break;  /* Entry Exists! */
  555.         ptr = (result<0)? ptr->lft : ptr->rgt;
  556.     }
  557.  
  558.     if( !result )
  559.     {   expr = AllocateNode();
  560.         expr->type = OpMember;
  561.         expr->rgt.set = ptr->defn;
  562.     } else expr = (Expr*)0;
  563.     return( expr );
  564. }
  565.  
  566.  
  567.  
  568. static int MatchWildName( src, dst, size, len )
  569.     char *src, *dst; int size, len;
  570. {
  571.     register int i, left;
  572.  
  573.     left = size;
  574.     while( *dst==' ' )
  575.     {   dst++; left--;
  576.     }
  577.  
  578.     for( i=0; i<len; i++ )
  579.     {   if( left )
  580.         {   if( (*dst==*src) || (*src=='?') )
  581.             {   dst++;  src++;  left--;
  582.             } else return( False );
  583.         } else if( *src++ != '?' )
  584.             return( False );
  585.     }
  586.  
  587.     while( left )
  588.          if( *dst++!=' ' )
  589.          {   return( False );
  590.          } else left--;
  591.     return( True );
  592. }
  593.  
  594.  
  595.  
  596. int ParsePrimitiveExpr( orig )
  597.     char **orig;
  598. {
  599.     static char NameBuf[4];
  600.     register Expr *tmp1,*tmp2;
  601.     register Expr *wild;
  602.     register char *ptr;
  603.     register int i, j;
  604.     register int neg;
  605.     register int ch;
  606.     
  607.     QueryExpr = &TrueExpr;
  608.     ptr = *orig;
  609.     ch = *ptr++;
  610.     i = 0;
  611.  
  612.     if( ch != '*' )
  613.     {   if( ch == '[' )
  614.         {   i = 0;
  615.             while( (ch = *ptr++) != ']' )
  616.                 if( ch && (i<3) )
  617.                 {   NameBuf[i++] = islower(ch)? toupper(ch) : ch;
  618.                 } else return( False );
  619.             ch = *ptr++;
  620.         } else
  621.             for( i=0; i<3; i++ )
  622.                 if( isalpha(ch) )
  623.                 {   NameBuf[i] = islower(ch)? toupper(ch) : ch;
  624.                     ch = *ptr++;
  625.                 } else if( (ch=='?') || (ch=='%') )
  626.                 {   NameBuf[i] = '?';
  627.                     ch = *ptr++;
  628.                 } else break;
  629.         if( !i ) return( False );
  630.  
  631.         wild = &FalseExpr;
  632.         for( j=0; j<ResNo; j++ )
  633.             if( MatchWildName(NameBuf,Residue[j],3,i) )
  634.             {   tmp1 = AllocateNode();
  635.                 tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  636.                 tmp1->lft.val = PropResName;
  637.                 tmp1->rgt.val = j;
  638.  
  639.                 tmp2 = AllocateNode();
  640.                 tmp2->type = OpOr;
  641.                 tmp2->lft.ptr = tmp1;
  642.                 tmp2->rgt.ptr = wild;
  643.                 wild = tmp2;
  644.             }
  645.         QueryExpr = wild;
  646.     } else ch = *ptr++;
  647.  
  648.     if( ch != '*' )
  649.     {   if( ch == '-' )
  650.         {   ch = *ptr++;
  651.             neg = True;
  652.         } else neg = False;
  653.  
  654.         if( isdigit(ch) )
  655.         {   i = ch-'0';
  656.             while( isdigit(*ptr) )
  657.                 i = 10*i + (*ptr++)-'0';
  658.  
  659.             tmp1 = AllocateNode();
  660.             tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  661.             tmp1->rgt.val = neg? -i : i;
  662.             tmp1->lft.val = PropResId;
  663.             if( QueryExpr != &TrueExpr )
  664.             {   tmp2 = AllocateNode();
  665.                 tmp2->type = OpAnd;
  666.                 tmp2->rgt.ptr = QueryExpr;
  667.                 tmp2->lft.ptr = tmp1;
  668.                 QueryExpr = tmp2;
  669.             } else QueryExpr = tmp1;
  670.             ch = *ptr++;
  671.         } else if( neg )
  672.             return( False );
  673.     } else ch = *ptr++;
  674.  
  675.     if( ch==':' )
  676.         ch = *ptr++;
  677.  
  678.     if( isalnum(ch) )
  679.     {   if( islower(ch) )
  680.             ch = toupper(ch);
  681.  
  682.         tmp1 = AllocateNode();
  683.         tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  684.         tmp1->lft.val = PropChain;
  685.         tmp1->rgt.val = ch;
  686.         if( QueryExpr != &TrueExpr )
  687.         {   tmp2 = AllocateNode();
  688.             tmp2->type = OpAnd;
  689.             tmp2->rgt.ptr = QueryExpr;
  690.             tmp2->lft.ptr = tmp1;
  691.             QueryExpr = tmp2;
  692.         } else QueryExpr = tmp1;
  693.         ch = *ptr++;
  694.     } else if( (ch=='?') || (ch=='%') || (ch=='*') )
  695.         ch = *ptr++;
  696.  
  697.     if( ch == '.' )
  698.     {   ch = *ptr++;
  699.         if( ch!='*' )
  700.         {   for( i=0; i<4; i++ )
  701.                 if( isalnum(ch) || ch=='\'' || ch=='*' )
  702.                 {   NameBuf[i] = islower(ch)? toupper(ch) : ch;
  703.                     ch = *ptr++;
  704.                 } else if( (ch=='?') || (ch=='%') )
  705.                 {   NameBuf[i] = '?';
  706.                     ch = *ptr++;
  707.                 } else break;
  708.             if( !i ) return( False );
  709.  
  710.  
  711.             wild = &FalseExpr;
  712.             for( j=0; j<ElemNo; j++ )
  713.                 if( MatchWildName(NameBuf,ElemDesc[j],4,i) )
  714.                 {   tmp1 = AllocateNode();
  715.                     tmp1->type = OpEqual | OpLftProp | OpRgtVal;
  716.                     tmp1->lft.val = PropName;
  717.                     tmp1->rgt.val = j;
  718.  
  719.                     tmp2 = AllocateNode();
  720.                     tmp2->type = OpOr;
  721.                     tmp2->lft.ptr = tmp1;
  722.                     tmp2->rgt.ptr = wild;
  723.                     wild = tmp2;
  724.                 }
  725.  
  726.             if( (QueryExpr == &TrueExpr) || (wild == &FalseExpr) )
  727.             {   DeAllocateExpr(QueryExpr);
  728.                 QueryExpr=wild;
  729.             } else
  730.             {   tmp1 = AllocateNode();
  731.                 tmp1->type = OpAnd;
  732.                 tmp1->lft.ptr = QueryExpr;
  733.                 tmp1->rgt.ptr = wild;
  734.                 QueryExpr = tmp1;
  735.             }
  736.         } else ch = *ptr++;
  737.     }
  738.     *orig = --ptr;
  739.     return( !ch || isspace(ch) || ispunct(ch) );
  740. }
  741.  
  742.  
  743. #if defined(__STDC__) || defined(IBMPC)
  744. /* Function Prototypes */
  745. static void DeleteSymEntry( SymEntry __far* );
  746. #endif
  747.  
  748.  
  749. static void DeleteSymEntry( ptr )
  750.     SymEntry __far *ptr;
  751. {
  752.     if( ptr->lft )
  753.         DeleteSymEntry( ptr->lft );
  754.     if( ptr->rgt )
  755.         DeleteSymEntry( ptr->rgt );
  756.  
  757.     if( ptr->defn )
  758.         DeleteAtomSet( ptr->defn );
  759.     free( ptr->ident );
  760.  
  761.     ptr->rgt = FreeEntry;
  762.     FreeEntry = ptr;
  763. }
  764.  
  765.  
  766. void ResetSymbolTable()
  767. {
  768.     if( SymbolTable )
  769.     {   DeleteSymEntry(SymbolTable);
  770.         SymbolTable = (void __far*)0;
  771.     }
  772. }
  773.  
  774.  
  775. void InitialiseAbstree()
  776. {
  777.     FalseExpr.type = OpConst | OpLftVal | OpRgtVal;
  778.     FalseExpr.rgt.val = FalseExpr.lft.val = 0;
  779.  
  780.     TrueExpr.type = OpConst | OpLftVal | OpRgtVal;
  781.     TrueExpr.rgt.val = TrueExpr.lft.val = 1;
  782.  
  783.     QChain = (void __far*)0;
  784.     QGroup = (void __far*)0;
  785.     QAtom = (void __far*)0;
  786.  
  787.     SymbolTable = (void __far*)0;
  788.  
  789.     FreeEntry = (void __far*)0;
  790.     FreeSet = (void __far*)0;
  791.     FreeExpr = NULL;
  792. }
  793.